# 改进：1. 增加大模型的temperature参数，并能在主页上用滑动条设置。
# 2. 在发送按钮旁边添加保存按钮，点击时弹出窗口，用户选择数据库文件路径后，按名称保存到数据库，默认使用”chat_日期时间.db“命名，不再保留/quit并点击发送时保存。
# 3. 在保存按钮旁边设置装载按钮，点击后弹出窗口，用户选择数据库文件后，在右侧的空间显示数据库中的对话记录。
# 4. 右侧的空间显示历史记录，初始化时为空，如果装载了对话记录，就显示对应内容，并把当前的对话记录也保存在这个数据库里。

# ----deepseek响应@  2025.2.27---------
# 增加 temperature 参数：在主页上添加滑动条，用户可设置 temperature。
# 保存按钮：点击保存按钮时，弹出窗口选择数据库文件路径，默认命名为 chat_日期时间.db。
# 装载按钮：点击装载按钮时，弹出窗口选择数据库文件，右侧显示历史记录。
# 右侧历史记录显示：初始化时为空，装载数据库后显示历史记录，并将当前对话记录保存到该数据库。


from flask import Flask, render_template, request, jsonify
import requests
import sqlite3
from datetime import datetime
import os

app = Flask(__name__)

# 智谱AI的 API 地址和密钥
from dotenv import load_dotenv
load_dotenv()  # 加载环境变量
API_KEY = os.getenv("ZHIPUAI_API_KEY")  # 从环境变量中获取 API 密钥
API_URL = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
model_name = "glm-4-flash"  # 使用的模型

# 全局变量存储当前数据库路径
dir_path = os.path.dirname(os.path.realpath(__file__))
current_db_name = 'chat_history.db'

# 调用智谱AI的 chat_models 模式
def call_zhipuai(messages, temperature):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    }
    data = {
        "model": model_name,  # 使用的模型
        "messages": messages,      # 对话上下文
        "temperature": temperature,  # 温度参数
        "stream": False            # 非流式返回
    }
    response = requests.post(API_URL, headers=headers, json=data)
    if response.status_code == 200:
        return response.json()["choices"][0]["message"]["content"]
    else:
        return f"Error: {response.status_code} - {response.text}"

# 保存对话历史到 SQLite 数据库
def save_chat_history(db_path, user_input, ai_response):
    
    current_db_name = os.path.join(dir_path, db_path) # 新增代码
    conn = sqlite3.connect(current_db_name)
    
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS chat_history
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  user_input TEXT,
                  ai_response TEXT)''')
    c.execute("INSERT INTO chat_history (user_input, ai_response) VALUES (?, ?)",
              (user_input, ai_response))
    conn.commit()
    conn.close()

# 加载对话历史从 SQLite 数据库
def load_chat_history(current_db_name):
    
    db_path = os.path.join(dir_path, current_db_name) # 新增代码
    if not os.path.exists(db_path):
        return []
    conn = sqlite3.connect(db_path)

    c = conn.cursor()
    c.execute("SELECT user_input, ai_response FROM chat_history")
    history = c.fetchall()
    conn.close()
    return history

# 主页路由
@app.route('/')
def index():
    return render_template('index_app02.html')

# 聊天路由
@app.route('/chat', methods=['POST'])
def chat():
    global current_db_name

    user_input = request.json.get('message')
    temperature = float(request.json.get('temperature', 0.7))
    session_messages = request.json.get('messages', [])
    session_messages.append({"role": "user", "content": user_input})

    # 调用智谱AI
    ai_response = call_zhipuai(session_messages, temperature)
    session_messages.append({"role": "assistant", "content": ai_response})
    
    # 如果当前数据库路径存在，保存对话历史
    if current_db_name:
        save_chat_history(current_db_name, user_input, ai_response)

    return jsonify({"response": ai_response, "messages": session_messages})

# 保存数据库路由
@app.route('/save_db', methods=['POST'])
def save_db():
    global current_db_name
    db_path = request.json.get('db_path')
    if not db_path:
        db_path = f"chat_history.db"  # 新增代码
        
    current_db_name = db_path
    
    load_chat_history(current_db_name)  # 新增代码
    
    return jsonify({"status": "success", "db_path": db_path})

# 加载数据库路由
@app.route('/load_db', methods=['POST'])
def load_db():
    global current_db_name
    current_db_name = request.json.get('db_path')   #只是文件名
    
    db_path = os.path.join(dir_path, current_db_name)
    if not os.path.exists(db_path):
        return jsonify({"status": "error", "message": "数据库文件不存在"})
    history = load_chat_history(current_db_name)
    return jsonify({"status": "success", "history": history})


if __name__ == '__main__':
    app.run(debug=True)